import * as cc from 'cc';
const { ccclass, property, executeInEditMode } = cc._decorator;

@ccclass('CameraTest1')
@executeInEditMode
export class CameraTest1 extends cc.Component {
    @property(cc.Node)
    cameraNode: cc.Node = null!;

    @property(cc.Node)
    target: cc.Node = null!;

    @property
    rotateX: number = 0;

    @property
    rotateY: number = 0;

    @property
    distance = 100;

    onLoad() {}

    start() {}

    update(deltaTime: number) {
        if (this.target && this.cameraNode) {
            // this.lookAtNode(this.target, this.cameraNode);
            this.lookAt(this.target, this.cameraNode);
            // this.moveAround(this.rotateX, this.rotateY, this.distance);
        }
    }

    moveAround(x: number, y: number, distance: number) {
        const pos = calculateOrbitPosition(
            this.target.worldPosition,
            distance,
            y,
            x,
        );
        this.cameraNode.position = pos;
    }

    // 朝向一个节点
    lookAtNode(target: cc.Node, cameraNode: cc.Node) {
        // 手动计算四元数：
        const direction = cc.Vec3.subtract(
            new cc.Vec3(),
            target.worldPosition,
            cameraNode.worldPosition,
        );
        const quat = new cc.Quat();
        cc.Quat.fromViewUp(quat, direction.normalize(), cc.Vec3.UP);
        cameraNode.setRotation(quat);
    }

    // Cocos 内置方法
    lookAt(target: cc.Node, cameraNode: cc.Node) {
        cameraNode.lookAt(target.worldPosition);
    }
}

/**
 * 计算相机位置（围绕目标旋转）
 * @param target 目标节点
 * @param distance 距离
 * @param thetaY 绕 Y 轴的角度（弧度）
 * @param phiX 绕 X 轴的角度（弧度）
 */
export function calculateOrbitPosition(
    target: cc.Vec3,
    distance: number,
    thetaY: number,
    phiX: number,
): cc.Vec3 {
    const radPhi = cc.math.toRadian(phiX);
    const radTheta = cc.math.toRadian(thetaY);
    const offsetX = distance * Math.sin(radPhi) * Math.sin(radTheta);
    const offsetY = distance * Math.cos(radPhi);
    const offsetZ = distance * Math.sin(radPhi) * Math.cos(radTheta);
    return new cc.Vec3(
        target.x + offsetX,
        target.y + offsetY,
        target.z + offsetZ,
    );
}
